

package jetbrains.buildServer.server.rest.model.problem.scope;

import java.util.List;
import java.util.stream.Collectors;
import jetbrains.buildServer.server.rest.data.util.tree.ScopeTree;
import jetbrains.buildServer.server.rest.data.util.tree.TreeCounters;
import jetbrains.buildServer.server.rest.model.Fields;
import jetbrains.buildServer.server.rest.util.BeanContext;
import org.apache.commons.lang3.BooleanUtils;
import org.jetbrains.annotations.NotNull;


public abstract class AbstractScopeTree<DATA, COUNTERS extends TreeCounters<COUNTERS>, N extends AbstractNode<DATA, COUNTERS>, L extends AbstractLeaf<DATA, COUNTERS>> {
  private List<ScopeTree.Node<DATA, COUNTERS>> myNodes;
  private Fields myFields;
  private BeanContext myContext;

  public AbstractScopeTree() { }

  public AbstractScopeTree(@NotNull List<ScopeTree.Node<DATA, COUNTERS>> sourceNodes, @NotNull Fields fields, @NotNull BeanContext context) {
    myNodes = sourceNodes;
    myFields = fields;
    myContext = context;
  }

  protected abstract N buildNode(@NotNull ScopeTree.Node<DATA, COUNTERS> source, @NotNull Fields fields);
  protected abstract L buildLeaf(@NotNull ScopeTree.Node<DATA, COUNTERS> source, @NotNull Fields fields, @NotNull BeanContext context);

  public List<N> getNodes() {
    if(BooleanUtils.isNotTrue(myFields.isIncluded("node"))) {
      return null;
    }

    Fields nodeFields = myFields.getNestedField("node");
    return myNodes.stream()
                  .map(node -> buildNode(node, nodeFields))
                  .collect(Collectors.toList());
  }

  public List<L> getLeafs() {
    if(BooleanUtils.isNotTrue(myFields.isIncluded("leaf"))) {
      return null;
    }

    Fields leafFields = myFields.getNestedField("leaf");
    return myNodes.stream()
                  .filter(node -> node.getData().size() > 0)
                  .map(node -> buildLeaf(node, leafFields, myContext))
                  .collect(Collectors.toList());
  }
}